﻿unit MemoryPool;

interface

uses
  System.SysUtils, MemBuffer, Protocol, MapBuffer, PoolBuffer;

type

  (* 内存池管理 *)
  TIMemoryPool = Class
  protected
    MapBuffer:          TIMapBuffer;    (* Buffer管理          *)
    FMapAcceptBuffer:   TIMapBuffer;    (* Accept Buffer管理   *)
    FPoolBuffer:        TIPoolBuffer;   (* Buffer回收池        *)
    PoolAcceptBuffer:   TIPoolBuffer;   (* Accept Buffer回收池 *)
  published
    property PoolBuffer: TIPoolBuffer read FPoolBuffer write FPoolBuffer;
    property MapAcceptBuffer: TIMapBuffer read FMapAcceptBuffer write FMapAcceptBuffer;
  public
    (* 初始化内存池               *)
    procedure InitMemoryPool(FreeBuffers: Integer);
    (* 分配Buffer               *)
    function AllocateBuffer(IOType: IO_POST_EVENT_TYPE): TIBuffer;
    (* 回收Buffer               *)
    function ReleaseBuffer(FBuffer: TIBuffer): Boolean;
    (* 释放Buffer               *)
    procedure FreeAllBuffers;
  public
    constructor Create;
    destructor Destroy; override;
  end;

implementation

{ TIMemoryPool }
constructor TIMemoryPool.Create;
begin
  inherited Create;
  FPoolBuffer := TIPoolBuffer.Create;
  FPoolBuffer.PoolBufferLock.SetLockName('PoolBuffer');
  PoolAcceptBuffer := TIPoolBuffer.Create;
  PoolAcceptBuffer.PoolBufferLock.SetLockName('AcceptPoolBuffer');

  MapBuffer := TIMapBuffer.Create;
  MapBuffer.MapBufferLock.SetLockName('MapBuffer');
  FMapAcceptBuffer:= TIMapBuffer.Create;
  FMapAcceptBuffer.MapBufferLock.SetLockName('MapAcceptBuffer');
end;

destructor TIMemoryPool.Destroy;
begin
  FreeAllBuffers;
  FreeAndNil(MapBuffer);
  FreeAndNil(FMapAcceptBuffer);
  FreeAndNil(FPoolBuffer);
  FreeAndNil(PoolAcceptBuffer);
  inherited Destroy;
end;

procedure TIMemoryPool.InitMemoryPool(FreeBuffers: Integer);
var
  i: Integer;
  FFreeBuffer: TIBuffer;
begin
  FPoolBuffer.SetMaxFreeBuffer(FreeBuffers);
  for i := 1 to FreeBuffers do
  begin
    FFreeBuffer := TIBuffer.Create;
    FPoolBuffer.ReleaseBufferToPool(FFreeBuffer);
  end;
  PoolAcceptBuffer.SetMaxFreeBuffer(500);
  for i := 1 to 500 do
  begin
    FFreeBuffer := TIBuffer.Create;
    FFreeBuffer.SetOperation(IO_WSA_ACCEPTEX);
    PoolAcceptBuffer.ReleaseBufferToPool(FFreeBuffer);
  end;
end;

function TIMemoryPool.AllocateBuffer(IOType: IO_POST_EVENT_TYPE): TIBuffer;
begin
  if IOType = IO_WSA_ACCEPTEX then
    begin
      Result := PoolAcceptBuffer.AllocateFreeBufferFromPool;
      Result.SetOperation(IOType);
      if MapAcceptBuffer.AddBuffer(Result) then
        begin
          {$IFDEF _ICOP_DEBUG}
          _GlobalLogger.AppendLogMessage('AllocateBuffer: IO_WSA_ACCEPTEX, %d', [m_PoolBuffer.m_nFreeBufferCount]);
          {$ENDIF}
        end
      else
        begin
          PoolAcceptBuffer.ReleaseBufferToPool(Result);
          {$IFDEF _ICOP_DEBUGERR}
          _GlobalLogger.AppendErrorLogMessage(IOCP_ERROR_ALLOCATE_BUFFER, []);
          {$ENDIF}
        end;
    end
  else
    begin
      Result := FPoolBuffer.AllocateFreeBufferFromPool;
      Result.SetOperation(IOType);
      if MapBuffer.AddBuffer(Result) then
        begin
          {$IFDEF _ICOP_DEBUG}
          case Result.GetOperation of
            IO_WSA_CLOSESOCKET:
            begin
              _GlobalLogger.AppendLogMessage('AllocateBuffer: IO_WSA_CLOSESOCKET, %d', [m_PoolBuffer.m_nFreeBufferCount]);
            end;
            IO_WSA_ACCEPTEX:
            begin
              _GlobalLogger.AppendLogMessage('AllocateBuffer: IO_WSA_ACCEPTEX, %d', [m_PoolBuffer.m_nFreeBufferCount]);
            end;
            IO_WSA_SEND:
            begin
              _GlobalLogger.AppendLogMessage('AllocateBuffer: IO_WSA_SEND, %d', [m_PoolBuffer.m_nFreeBufferCount]);
            end;
            IO_WSA_RECV:
            begin
              _GlobalLogger.AppendLogMessage('AllocateBuffer: IO_WSA_RECV, %d', [m_PoolBuffer.m_nFreeBufferCount]);
            end;
          end;
          {$ENDIF}
        end
      else
        begin
          PoolBuffer.ReleaseBufferToPool(Result);
          {$IFDEF _ICOP_DEBUGERR}
          _GlobalLogger.AppendErrorLogMessage(IOCP_ERROR_ALLOCATE_BUFFER, []);
          {$ENDIF}
        end;
    end;
end;

function TIMemoryPool.ReleaseBuffer(FBuffer: TIBuffer): Boolean;
begin
  {$IFDEF _ICOP_DEBUGERR}
  if FBuffer.GetOperation = IO_INITIALIZE then
    _GlobalLogger.AppendErrorLogMessage('TIMemoryPool.ReleaseBuffer IO_INITIALIZE ', []);
  {$ENDIF}
  if FBuffer.GetOperation = IO_WSA_ACCEPTEX then
    begin
      Result := FMapAcceptBuffer.RemoveBuffer(FBuffer);
      PoolAcceptBuffer.ReleaseBufferToPool(FBuffer);
    end
  else
    begin
      Result := MapBuffer.RemoveBuffer(FBuffer);
      FPoolBuffer.ReleaseBufferToPool(FBuffer);
    end;
end;

procedure TIMemoryPool.FreeAllBuffers;
begin
  (* 释放FAcceptExMapBuffer中Buffer 释放内存池中Buffer *)
  {$IFDEF _ICOP_DEBUGCLOSE}
  _GlobalLogger.AppendLogMessage(IOCP_ERROR_RELEASE_MAPBUFFER, [m_MapBuffer.GetActiveBufferCount]);
  _GlobalLogger.AppendLogMessage(IOCP_ERROR_RELEASE_ACCEPTMAPBUFFER, [m_MapAcceptBuffer.GetActiveBufferCount]);
  _GlobalLogger.AppendLogMessage(IOCP_ERROR_RELEASE_POOLBUFFER, [m_PoolBuffer.GetBufferCount]);
  _GlobalLogger.AppendLogMessage(IOCP_ERROR_RELEASE_POOLACCEPTBUFFER, [m_PoolAcceptBuffer.GetBufferCount]);
  {$ENDIF}
  MapBuffer.FreeBuffers;
  FMapAcceptBuffer.FreeBuffers;
  FPoolBuffer.FreeBuffers;
  PoolAcceptBuffer.FreeBuffers;
end;

end.
